/******************************************************************************

    Copyright (C) 2006 Alessio Stalla (alessiostalla@gmail.com)

    This file is part of PrettyProlog.

    PrettyProlog is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    PrettyProlog is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PrettyProlog; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    See the file COPYING for further details.

 *****************************************************************************/

package prettyprolog.engine;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import prettyprolog.datatypes.Callable;
import prettyprolog.datatypes.Term;
import prettyprolog.datatypes.Variable;

/**
 * A Goal is a list of Terms, representing a question to the Engine. The
 * question is to be answered with all the Substitutions that unify the goal
 * with a fact (i.e. a Clause or system predicate which is true).
 */
public class Goal extends LinkedList<Term> implements Serializable {

	private static final long serialVersionUID = 1L;

	/** Creates an empty Goal. */
	public Goal() {
		super();
	}

	/** Creates a Goal copying from another Goal. */
	public Goal(Goal copy) {
		this((List<Term>) copy);
	}

	/**
	 * Creates a Goal copying from a list of terms. Assumes that super(copy)
	 * will call the add() method.
	 */
	public Goal(List<Term> copy) {
		super(copy);
	}
	
	public Goal(Term... terms) {
		this(Arrays.asList(terms));
	}

	/**
	 * Adds a Term to this Goal.
	 * 
	 * @param t
	 *            the Term to be added. It must be an instance of Callable or
	 *            Variable.
	 * @throws IllegalArgumentException
	 *             if the Term is neither a Callable nor a Variable.
	 */
	public boolean add(Term t) throws IllegalArgumentException {
		if ((t instanceof Callable) || (t instanceof Variable)) {
			return super.add(t);
		} else {
			throw new IllegalArgumentException();
		}
	}
	
	public void add(int index, Term t) throws IllegalArgumentException {
		if ((t instanceof Callable) || (t instanceof Variable)) {
			super.add(index, t);
		} else {
			throw new IllegalArgumentException();
		}
	}

	/**
	 * Returns the subgoal beginning at start (inclusive) and ending at end
	 * (exclusive).
	 */
	public Goal subList(int start, int end) {
		return new Goal(super.subList(start, end));
	}

	/** true if the Goal doesn't contain any free variables, false otherwise. */
	public boolean isGround() {
		Iterator<Term> it = iterator();
		while (it.hasNext()) {
			if (!it.next().isGround(false))
				return false;
		}
		return true;
	}

	public String toString() {
		String s = "";
		for (Term t : this) {
			if (s.length() > 0)
				s += ", ";
			s += t;
		}
		return s;
	}

}